<template>
  <div class="wrap">
    <pro-table
      ref="proTableInst"
      tableTitle="角色列表"
      :columns="columns"
      :request="fetchRolePage"
      auto-height
    >
      <template #operation>
        <n-space>
          <n-button type="primary" @click="handleAddRole">新增角色</n-button>
        </n-space>
      </template>
    </pro-table>

    <n-drawer
      v-model:show="drawerShow"
      :width="500"
      resizable
      :maskClosable="false"
      @after-leave="resetRoleForm"
    >
      <n-drawer-content closable :title="handleTag">
        <pro-form
          ref="roleFormInst"
          v-model:form="roleForm"
          :options="roleFormOptions"
          :formProps="{
            labelPlacement: 'left'
          }"
        ></pro-form>

        <template #footer>
          <n-space>
            <n-button @click="drawerShow = false">取消</n-button>
            <n-button type="primary" @click="roleConfirm">确认</n-button>
          </n-space>
        </template>
      </n-drawer-content>
    </n-drawer>

    <pro-modal
      v-model:show="editFuncModal"
      title="编辑权限"
      :maxHeight="500"
      :loading="editFuncModalLoading"
      @afterLeave="handleFuncModalAfterLeave"
      @ok="fetchEditRoleFunc"
    >
      <n-tree
        @updateCheckedKeys="(keys) => (roleFuncList = keys)"
        :checkedKeys="roleFuncList"
        :data="funcTree"
        keyField="id"
        labelField="funcName"
        block-line
        cascade
        checkable
      />
    </pro-modal>
  </div>
</template>

<script lang="ts" setup name="RoleList">
  import { ProTableInst } from '@/components/pro-table/type'
  import { ProFormInst } from '@/components/pro-form/type'
  import { useRoleApi, useRoleProForm, useRoleProTable } from './hooks'
  import { useHasPermi } from '@/hooks/useHasPermi'

  const proTableInst = ref<ProTableInst | null>(null)
  const roleFormInst = ref<ProFormInst | null>(null)

  const drawerShow = ref(false)
  const handleType = ref<'add' | 'edit' | ''>('')
  const handleTag = computed(() =>
    handleType.value === 'add' ? '新增角色' : '修改角色'
  )

  const funcTree = ref([])
  const roleFuncList = ref<number[]>([])
  const currentRole = ref<any>({})
  const editFuncModal = ref(false)
  const { roleForm, resetRoleForm, roleFormOptions } = useRoleProForm()

  const handleAddRole = () => {
    handleType.value = 'add'
    drawerShow.value = true
  }

  const handleEditRole = (row) => {
    roleForm.value = row
    handleType.value = 'edit'
    drawerShow.value = true
  }

  const handleGrantRolePerm = (row) => {
    editFuncModal.value = true
    editFuncModalLoading.value = true
    currentRole.value = row
    forFuncTree(funcTree.value)
    roleFuncList.value =
      currentRole.value.menuIds?.map((item) => parseInt(item)) || []
    editFuncModalLoading.value = false
  }

  const handleFuncModalAfterLeave = () => {
    roleFuncList.value = []
    // funcTree.value = []
    currentRole.value = {}
  }

  const roleConfirm = async () => {
    if (await roleFormInst.value?.handleSubmit()) {
      fetchAddOrEditRole()
    }
  }

  function forFuncTree(treeList) {
    treeList.forEach((treeItem) => {
      if (treeItem.children && treeItem.children?.length > 0) {
        const find = currentRole.value.menuIds.find(
          (item) => item === treeItem.id.toString()
        )
        if (find) {
          currentRole.value.menuIds = currentRole.value.menuIds.filter(
            (item) => item !== treeItem.id.toString()
          )
        }
        forFuncTree(treeItem.children)
      }
    })
  }

  const {
    fetchRolePage,
    fetchAddOrEditRole,
    fetchDelRole,
    changeRoleStatus,
    fetchRoleAllFunc,
    fetchEditRoleFunc,
    roleStatusLoading,
    editFuncModalLoading
  } = useRoleApi({
    handleType,
    handleTag,
    drawerShow,
    roleForm,
    proTableInst,
    currentRole,
    roleFuncList,
    editFuncModal,
    funcTree
  })

  fetchRoleAllFunc()

  const { columns } = useRoleProTable({
    handleEditRole,
    fetchDelRole,
    changeRoleStatus,
    handleGrantRolePerm,
    roleStatusLoading
  })
</script>

<style lang="less" scoped></style>
